#include "topconn_factory.hpp"
#include "topconn_exception.hpp"
#include "topconn_connector.hpp"

#include <string.h>

#include "protocal/tcp/tcpconnector.hpp"
#include "protocal/udp/udpconnector.hpp"
#include "protocal/http/httpconnector.hpp"
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
#include "protocal/https/httpsconnector.hpp"
#endif
#include "protocal/mq/posix/posixconnector.hpp"

#ifdef IBMMQ_SUPPORT
#include "protocal/mq/ibm/mqconnector.hpp"
#endif

#ifdef OPENSSL_SUPPORT
#include "protocal/tcp_ssl/ssl_tcpconnector.hpp"
#endif

#ifdef SSH_SFTP_SUPPORT
#include "protocal/sftp/sftpconnector.hpp"
#endif // SSH_SFTP_SUPPORT

#ifdef CIBCTSP_SUPPORT
#include "protocal/ctsp/ctspconnector.hpp"
#endif

namespace topconn
{
	typedef enum {
		topconn_none = 0,
		topconn_tcp,
		topconn_udp,
		topconn_http,
		topconn_https,
		topconn_mq_posix,
		topconn_mq_ibm,
		topconn_tcp_ssl,
		topconn_sftp,
		topconn_cib_ctsp,
		topconn_cib_ofep,
		topconn_unkown = (int)(((unsigned int)(-1)) / 2)
	}eProtocalType_t;

	static struct
	{
		char xProtocalName[20];
		eProtocalType_t xProtocalType;
	}fProtocal_t[] =
	{
		{"none",topconn_none},
		{"tcp", topconn_tcp},
		{"udp", topconn_udp},
		{"http", topconn_http},
		{"https", topconn_https},
		{"mq:posix", topconn_mq_posix},
		{"mq:ibm", topconn_mq_ibm},
		{"tcp:ssl", topconn_tcp_ssl},
		{"sftp", topconn_sftp},
		{"cib:ctsp",topconn_cib_ctsp},
		{"cib:ofep",topconn_cib_ofep},
		{"",topconn_unkown}
	};

	class NoneConnector : public Connector
	{
	public:
		void checkElementCfgValid(AttributeableCfg& cfg) {};
		int  executor(ProtocalCfg& cfg, const string& request, string& resopnse,const string& atx) { return 0; };
	};

	int ProtocalType::getProtocalType(const string& protocalType)
	{
		eProtocalType_t type = eProtocalType_t::topconn_unkown;
		for (int i = 0; i < sizeof(fProtocal_t) / sizeof(fProtocal_t[0]); i++)
		{
			if (strcmp(fProtocal_t[i].xProtocalName, protocalType.c_str()) == 0)
			{
				type = fProtocal_t[i].xProtocalType;
				break;
			}
		}
		return (int)type;
	}

	string ProtocalType::getProtocalType(int protocalType)
	{
		string name = "unkown protocol";
		for (int i = 0; i < sizeof(fProtocal_t) / sizeof(fProtocal_t[0]); i++)
		{
			if (protocalType == (int)fProtocal_t[i].xProtocalType)
			{
				name = fProtocal_t[i].xProtocalName;
				break;
			}
		}
		return name;
	}

	ConnectorPtr_t ConnectorFactory::create(const string& protocalType)
	{
		int type = ProtocalType::getProtocalType(protocalType);
		switch (type)
		{
		case topconn_none:
			return std::make_shared<NoneConnector>();
		case topconn_tcp:
			return std::make_shared<TcpConnector>();
		case topconn_udp:
			return std::make_shared<UdpConnector>();
		case topconn_http:
			return std::make_shared<HttpConnector>();
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
		case topconn_https:
			return std::make_shared<HttpsConnector>();
#endif
		case topconn_mq_posix:
			return std::make_shared<PosixConnector>();
#ifdef IBMMQ_SUPPORT
		case topconn_mq_ibm:
			return std::make_shared<MqmConnector>();
#endif
#ifdef OPENSSL_SUPPORT
		case topconn_tcp_ssl:
			return std::make_shared<SSLTcpConnector>();
#endif
#ifdef SSH_SFTP_SUPPORT
		case topconn_sftp:
			return std::make_shared<SftpConnector>();
#endif
#ifdef CIBCTSP_SUPPORT
		case topconn_cib_ctsp:
			return std::make_shared<CtspConnector>();
		case topconn_cib_ofep:
			return std::make_shared<OfepConnector>();
#endif
		default:
			throw ConnException("Unsupported communication protocol policy type:"+ protocalType);
			break;
		}
	};
};
